/*
 这个类应当包含于观看视频直播的播放器中
 */
#include <QStringList>
#include <QTimer>
#include "p2ppeer.h"
#include <QUdpSocket>
#include "macro.h"
#include "dialog.h"
#include "ui_dialog.h"
#include "p2pserver.h"
#include "threadpeer.h"
#include "udpComunInPTh.h"

P2PPeer::P2PPeer(QObject *parent) :
    QObject(parent)
{
    udpSocketForDistri=NULL;

    timerForTTL=new QTimer(this);
    timerForTTL->start(5300);
    connect(timerForTTL,SIGNAL(timeout()),this,SLOT(timerForTTLEvent()));
    //需要发送数据给peer时，把数据交给负责发送的线程

    QTimer tempTimer;
    for(int n=0;n<PEER_THREAD_NUM;n++)
    {
        ThreadPeer* temp=new ThreadPeer(n,this);
        temp->start(QThread::NormalPriority);
        listThreadPeer.append(temp);
    }
    //10000ms以后进行连接。现在，新的thread还在构造中.同时，等待系统初始化的完成
    tempTimer.singleShot(10000,this,SLOT(connectThread()));

}


void    P2PPeer::addOneChild(QString childSocket, qint64 macAddr)
{
    addrChildSocketMap.insert(childSocket,macAddr);
    childSocketTTLMap.insert(childSocket,P2P_TTL_MAX);
}

void    P2PPeer::removeOneChild(QString childSocket, qint64 macAddr)
{
    addrChildSocketMap.remove(childSocket,macAddr);
    childSocketTTLMap.remove(childSocket);
}

void    P2PPeer::distriVideo(QByteArray &data, qint64 macAddr)
{
    QString strIP,strPort;
    QString item;
    bool ok;
    dataToBeSent=data;

    QStringList  childSocketList=addrChildSocketMap.keys(macAddr);

    for(int ind=0;ind<childSocketList.count();ind++)
    {
        item=childSocketList.at(ind);
        strIP=item.split(":").at(0);
        strPort=item.split(":").at(1);

        QByteArray byteSN;
        byteSN.append(dataToBeSent.mid(8,1)); //前8个字节是源地址，第9个字节是SN
        quint8 tempID=((WeatherStation*)parent())->curntThreadPeerID;
        emit sigSendData(dataToBeSent,strIP,strPort.toUShort(&ok,10),tempID);
        ((WeatherStation*)parent())->curntThreadPeerID=(tempID+1)%PEER_THREAD_NUM;
        if(((WeatherStation*)parent())->ui->checkBoxShowText->isChecked())
         ((WeatherStation*)parent())->ui->receivedPlainTextEdit->appendPlainText(
                 "Video sent to"+strIP+",SN is"+QString::number(
                         byteSN.toHex().toShort(&ok,16),10));
    }
}

void    P2PPeer::setUdpSocket(QUdpSocket *udpSocket)
{
    udpSocketForDistri=udpSocket;
}

void    P2PPeer::timerForTTLEvent()
{
    //childSocketTTLMap.
    bool ok;
    QMapIterator<QString,qint8> i(childSocketTTLMap);  //遍历整个map
    while (i.hasNext())
    {
        i.next();
        if(i.value()<=0) //该TTL过期
        {
            addrChildSocketMap.remove(i.key());  //作相应处理
            childSocketTTLMap.remove(i.key());
            if(i.key().split(":").size()>=2)
            {
             notifyPeerDisconnected(QHostAddress( i.key().split(":").at(0)),
                QString(i.key().split(":").at(1)).toUShort(&ok,10));

             P2PServer * p2pServer=((WeatherStation*)parent())->myP2pServer;
             if(p2pServer)
                p2pServer->doWithDeadSocket(i.key().split(":").at(0),i.key().split(":").at(1));
            }
        }
        else
            childSocketTTLMap.insert(i.key(),i.value()-1);
    }
}

QByteArray   P2PPeer::updateChildSocketTTLMap(QString socket)
{
    if(childSocketTTLMap.contains(socket))  //如果包含该项，则更新
    {
        childSocketTTLMap.insert(socket,P2P_TTL_MAX);
        return tr("INFO:心跳已处理").toUtf8();
    }
    else
        return  tr("INFO:连接已断开或尚未建立连接").toUtf8();
}

void  P2PPeer::notifyPeerDisconnected(QHostAddress iP, quint16 port)
{
    QByteArray  dataGram=QByteArray::fromHex("WARNING:Disconnected");
    if(!iP.toString().isEmpty()&&iP.toString().count(".")==3)
        udpSocketForDistri->writeDatagram(dataGram,iP,port);
}

void  P2PPeer::testThread()
{
    //emit sigSendData("33","127.0.0.1",9999,0);
}

void P2PPeer::connectThread()
{
    for(int n=0;n<PEER_THREAD_NUM;n++)
    {
        if(listThreadPeer.at(n)->udpComInPeerThread)
            connect(this,SIGNAL(sigSendData(QByteArray,QString,quint16,quint8)),
               listThreadPeer.at(n)->udpComInPeerThread,SLOT(slotSendData(QByteArray,QString,quint16,quint8)));

    }
}

void P2PPeer::quitThreadPeers()
{
    for(int n=0;n<PEER_THREAD_NUM;n++)
    {
        ThreadPeer* temp=listThreadPeer.at(0);
        temp->exit();
        temp->wait(500);
        listThreadPeer.removeFirst();
    }
}
